import { getStandardTypeByCellType } from "../constants"

export class vtkReader {
    dataSetMap: Map<string, any[]>
    attributes: any = {}

    async read(url: string) {
        await this.readFile(url).then((lines) => {
            const version = this.checkVersion(lines[0])
            if (version === 3) {
                this.parseV3(lines)
            }
        })
    }

    async readFile(url: string): Promise<string[]> {
        try {
            const response = await fetch(url)
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`)
            }
            const text = await response.text()
            return text
                .split("\n")
                .map((line) => line.trim())
                .filter((line) => line.length > 0)
        } catch (error) {
            console.error("Error reading VTK file:", error)
            throw error
        }
    }

    checkVersion(firstLine: string) {
        const version = Math.floor(+firstLine.split("Version ")[1])
        return version
    }

    parseV3(lines: string[]) {
        const dataSetMap = new Map<string, any[]>()
        let currentDataSet: string = null
        let currentAttribute = ""
        for (let i = 0; i < lines.length; i++) {
            if (lines[i].startsWith("DATASET")) {
                const dataSetType = lines[i].split(" ")[1]
                if (dataSetType !== "UNSTRUCTURED_GRID") {
                    return `Unsupported dataset type: ${dataSetType}`
                }
            }
            if (lines[i].startsWith("POINTS")) {
                dataSetMap.set("POINTS", [])
                currentDataSet = "POINTS"
                continue
            }
            if (lines[i].startsWith("CELLS")) {
                dataSetMap.set("CELLS", [])
                currentDataSet = "CELLS"
                continue
            }
            if (lines[i].startsWith("CELL_TYPES")) {
                dataSetMap.set("CELL_TYPES", [])
                currentDataSet = "CELL_TYPES"
                continue
            }
            if (lines[i].startsWith("POINT_DATA")) {
                currentDataSet = "POINT_DATA"
                continue
            }
            if (
                currentDataSet === "POINT_DATA" &&
                lines[i].startsWith("VECTORS")
            ) {
                const name = lines[i].split(" ")[1]
                currentAttribute = name
                this.attributes[name] = {
                    name: lines[i].split(" ")[1],
                    x: [],
                    y: [],
                    z: [],
                    Magnitude: [],
                    size: 3,
                }
                continue
            }
            if (lines[i] === "") {
                continue
            }
            // * 处理几何数据
            switch (currentDataSet) {
                case "POINTS":
                    dataSetMap.get("POINTS").push(
                        ...lines[i]
                            .trim()
                            .replace(/\s+/g, ",")
                            .split(",")
                            .map((s) => +(+s).toFixed(3))
                    )
                    break
                case "CELLS":
                    const tmp = lines[i].split(" ")
                    dataSetMap.get("CELLS").push({
                        pointCount: +tmp[0],
                        nodeIds: tmp.slice(1).map((s) => +s),
                    })
                    break
                case "CELL_TYPES":
                    dataSetMap.get("CELL_TYPES").push(+lines[i])
            }
            // * 处理物理量数据
            if (currentAttribute) {
                const data = lines[i]
                    .trim()
                    .replace(/\s+/g, ",")
                    .split(",")
                    .map((s) => +(+s).toFixed(3))
                this.attributes[currentAttribute].x.push(data[0])
                this.attributes[currentAttribute].y.push(data[1])
                this.attributes[currentAttribute].z.push(data[2])
                this.attributes[currentAttribute].Magnitude.push(
                    Math.sqrt(
                        data[0] * data[0] +
                            data[1] * data[1] +
                            data[2] * data[2]
                    )
                )
            }
        }
        this.dataSetMap = dataSetMap
    }

    getStandardJsonObject() {
        const container = {
            nodes: [],
            nodeIds: [],
            elements: [],
        }
        container.nodeIds = Array.from(
            { length: this.dataSetMap.get("POINTS").length / 3 },
            (_, i) => i
        )
        container.nodes = this.dataSetMap.get("POINTS")
        container.elements = this.dataSetMap.get("CELLS").map((cell, i) => ({
            nodeIds: cell.nodeIds,
            eid: i,
            type: getStandardTypeByCellType(
                this.dataSetMap.get("CELL_TYPES")[i]
            ),
        }))
        return container
    }
}
